package com.burgeon.backend.SHOPBACKEND.service.Impl;

import cn.jiguang.common.utils.Nullable;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.burgeon.backend.SHOPBACKEND.entity.Article;
import com.burgeon.backend.SHOPBACKEND.entity.Media;
import com.burgeon.backend.SHOPBACKEND.entity.NewsItem;
import com.burgeon.backend.SHOPBACKEND.service.MessageNewsService;
import com.burgeon.backend.SHOPBACKEND.service.ex.DataNotFoundException;
import com.burgeon.backend.SHOPBACKEND.service.ex.UploadException;
import com.burgeon.backend.Util.menu.MyX509TrustManager;
import com.burgeon.backend.service.WechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class MessageNewsServiceImpl implements MessageNewsService {
    @Autowired
    private WechatService wechatService;

    private static String UPLOAD_IMG_URL="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN";
    private static String UPLOAD_NEWS_URL="https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=ACCESS_TOKEN";
    private static String ADD_NEWS_URL="https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN";
    private static String SEND_NEWS_URL="https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN";
    private static String SENDAll_NEWS_URL="https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=ACCESS_TOKEN";
    private static String PREVIEW_NEWS_URL="https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN";
    private static String ADD_material="https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE";
    private static String GET_NEWS_URL="https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN";
    private static String UPDATE_NEWS_URL="https://api.weixin.qq.com/cgi-bin/material/update_news?access_token=ACCESS_TOKEN";
    private static String DELETE_NEWS_URL="https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN";


    /**
     * 删除图文素材
     * @param account
     * @param media_id
     */
    public void deleteNews(String account,String media_id) throws UnsupportedEncodingException {
        String accessToken = wechatService.GetAccesTokenByAccount(account);
        JSONObject data = new JSONObject();
        data.put("media_id", media_id);//要修改的图文消息的id
        JSONObject res = doPostStr(DELETE_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
        System.err.println(res); 
    }

    /**
     * 修改图文素材
     * @param account
     */
    public void updateNews(Article articles,String account,String media_id,String index) throws UnsupportedEncodingException {
        String accessToken = wechatService.GetAccesTokenByAccount(account);
        JSONObject data = new JSONObject();
        data.put("media_id", media_id);//要修改的图文消息的id
        data.put("index", index);//要更新的文章在图文消息中的位置（多图文消息时，此字段才有意义），第一篇为0
        data.put("articles",articles);
        JSONObject res = doPostStr(UPDATE_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
        System.err.println(res);
    }


    /**
     * 获取图文素材列表
     * @param account
     */
    public ArrayList<NewsItem> getNews(String account) throws UnsupportedEncodingException {
        String accessToken = wechatService.GetAccesTokenByAccount(account);
        JSONObject data = new JSONObject();
        data.put("type","news");//素材的类型，图片（image）、视频（video）、语音 （voice）、图文（news）
        data.put("offset","0");//从全部素材的该偏移位置开始返回，0表示从第一个素材 返回
        data.put("count","20");//返回素材的数量，取值在1到20之间
        JSONObject res = doPostStr(GET_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
//        String itemCount=res.getString("item_count");
//        System.err.println(itemCount);
//        System.err.println(res);
        JSONArray jsonArray = res.getJSONArray("item");

        ArrayList<NewsItem> newsItems = new ArrayList<>();

        for (int i=0;i<jsonArray.size();i++){

            NewsItem newsItem = new NewsItem();
            ArrayList<Article> articles = new ArrayList<>();

            newsItem.setMedia_id(jsonArray.getJSONObject(i).getString("media_id"));
            String upTime = formatTime(jsonArray.getJSONObject(i).getString("update_time"));
            newsItem.setUpdateTime(upTime);
            System.err.println(upTime);

            String content = jsonArray.getJSONObject(i).getString("content");
            JSONObject json = JSONObject.parseObject(content);
            JSONArray jsonArray1 = json.getJSONArray("news_item");
            for (int j=0;j<jsonArray1.size();j++){

                Article article = new Article();
                article.setThumb_url(jsonArray1.getJSONObject(j).getString("thumb_url"));
                article.setThumb_media_id(jsonArray1.getJSONObject(j).getString("thumb_media_id"));
                article.setAuthor(jsonArray1.getJSONObject(j).getString("author"));
                article.setTitle(jsonArray1.getJSONObject(j).getString("title"));
                article.setUrl(jsonArray1.getJSONObject(j).getString("url"));
                article.setShow_cover_pic(jsonArray1.getJSONObject(j).getInteger("show_cover_pic"));
                article.setDigest(jsonArray1.getJSONObject(j).getString("digest"));
                article.setContent(jsonArray1.getJSONObject(j).getString("content"));
                article.setContent_source_url(jsonArray1.getJSONObject(j).getString("content_source_url"));
                articles.add(article);
            }
            newsItem.setArticles(articles);
//            System.err.println(jsonArray1);
//            System.err.println(jsonObject.getJSONArray("content"));
//            System.err.println(jsonArray.getJSONObject(i));
            newsItems.add(newsItem);
        }
//        System.err.println(newsItems);
        return newsItems;

    }
    /**
     * 将微信消息中的CreateTime转换成标准格式的时间（yyyy-MM-dd HH:mm:ss）
     * @param createTime 消息创建时间
     * @return
     */
    public static String formatTime(String createTime) {

        // 将微信传入的CreateTime转换成long类型，再乘以1000
        long msgCreateTime = Long.parseLong(createTime) * 1000L;

        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return format.format(new Date(msgCreateTime));

    }


    /**
     * 上传永久素材图片
     */
    public Media addMaterial(MultipartFile img, String account){
        if (null == img || img.isEmpty()) {
            System.out.println("文件为空");
            throw new UploadException("文件为空");
        }else if(null == account || account.isEmpty()){
            throw new UploadException("客户标识没有传");
        }
        // 保存到本地，获取本地图片绝对路径
        String filePath = saveFile(img,account);
//        String filePath = img.getName();
        String accessToken = wechatService.GetAccesTokenByAccount(account);
        String type = "thumb";
        try {
            JSONObject res =uploadFile(ADD_material, filePath, accessToken, type);
            System.err.println(res);
            Media m = new Media();
            m.setMedia_id(res.getString("media_id"));
            m.setUrl(res.getString("url"));
            return m;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根OpenID群发图文消息
     * @param openIds OpenID集合
     * @param media_id 图文消息媒体编号
     * @return msg_id
     * @throws Exception 发送失败
     */
    @Override
    public String sendNewsByOpenIds(List<String> openIds, String media_id,String account) throws UnsupportedEncodingException {
        JSONObject data = new JSONObject();
          //预览接口仅支持一个openID
//        data.put("touser", openIds.get(0));
        if(openIds.size()==1){
            data.put("touser", openIds.get(0));
            Map<String, String> npnews = new HashMap<>();
            npnews.put("media_id", media_id);
            data.put("mpnews", npnews);
            data.put("msgtype", "mpnews");
            data.put("send_ignore_reprint", 0);
            String accessToken = wechatService.GetAccesTokenByAccount(account);
//            System.err.println(openIds);
            JSONObject res = doPostStr(PREVIEW_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
//            System.err.println(res);
            if(0!=res.getIntValue("errcode")) {
                // 发送失败
//          throw new CustomException(ResultEnum.SEND_NEWS_FAILURE);
                log.info("发送图文失败"+res.getIntValue("errcode"));
                throw new DataNotFoundException("发送图文失败"+res.getIntValue("errcode"));
            } else {
                return res.getString("msg_id");
            }
        }
        data.put("touser", openIds);
        Map<String, String> npnews = new HashMap<>();
        npnews.put("media_id", media_id);
        data.put("mpnews", npnews);
        data.put("msgtype", "mpnews");
        data.put("send_ignore_reprint", 0);
        String accessToken = wechatService.GetAccesTokenByAccount(account);
//        System.err.println(openIds);
        JSONObject res = doPostStr(SEND_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
        System.err.println(res);
        if(0!=res.getIntValue("errcode")) {
            // 发送失败
//          throw new CustomException(ResultEnum.SEND_NEWS_FAILURE);
            log.info("发送图文失败"+res.getIntValue("errcode"));
            throw new DataNotFoundException("发送图文失败"+res.getIntValue("errcode"));
        } else {
            return res.getString("msg_id");
        }
//return null;
    }

    /**
     * 根OpenID群发图文消息
     * @param media_id 图文消息媒体编号
     * @return msg_id
     * @throws Exception 发送失败
     */
    @Override
    public String sendNewsAll(String media_id,String account) throws UnsupportedEncodingException {
        JSONObject data = new JSONObject();
        // 预览接口仅支持一个openID
//        data.put("touser", openIds.get(0));
//        data.put("touser", openIds);
        Map<String, String> filter = new HashMap<>();
        filter.put("is_to_all","true");
        data.put("filter",filter);
        Map<String, String> npnews = new HashMap<>();
        npnews.put("media_id", media_id);
        data.put("mpnews", npnews);
        data.put("msgtype", "mpnews");
        data.put("send_ignore_reprint", 0);
        String accessToken = wechatService.GetAccesTokenByAccount(account);
        JSONObject res = doPostStr(SENDAll_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
        System.err.println(res);
        if(0!=res.getIntValue("errcode")) {
            // 发送失败
//            throw new CustomException(ResultEnum.SEND_NEWS_FAILURE);
            log.info("发送图文失败"+res.getIntValue("errcode"));
            throw new DataNotFoundException("发送图文失败"+res.getIntValue("errcode"));
        } else {
            return res.getString("msg_id");
        }

    }


    /**
     * 上传图文消息素材
     * @param articles 图文消息集合
     * @return media_id
     */
    @Override
    @Nullable
    public String postNews(Article[] articles, String account) throws UnsupportedEncodingException {
        JSONObject data = new JSONObject();
        data.put("articles", articles);
        String accessToken = wechatService.GetAccesTokenByAccount(account);
        System.err.println(data.toJSONString());
        JSONObject res = doPostStr(ADD_NEWS_URL.replace("ACCESS_TOKEN", accessToken), data.toJSONString());
        System.err.println(res);
        return res.getString("media_id");
    }

    /**
     * 上传图文信息图片
     * @param account
     * @param img 图片
     * @return url
     */
    @Override
    //@Nullable
    public String postImg(MultipartFile img,String account) {
        if (null == img || img.isEmpty()) {
            System.out.println("文件为空");
            throw new UploadException("文件为空");
        }else if(null == account || account.isEmpty()){
            throw new UploadException("客户标识没有传");
        }
        // 保存到本地，获取本地图片绝对路径
        String filePath = saveFile(img,account);
        //String filePath = img.getName();
        String accessToken = wechatService.GetAccesTokenByAccount(account);

        JSONObject res = doPostForm(UPLOAD_IMG_URL.replace("ACCESS_TOKEN", accessToken), filePath);
        System.err.println(res);
        return res.getString("url");
    }

    /**
     * POST请求 - JSON格式数据
     * @param url
     * @param outStr
     * @return
     */
    public JSONObject doPostStr(String url, String outStr) throws UnsupportedEncodingException {
        System.err.println(outStr);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json;charset=UTF-8");// 解决请求乱码问题
        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.postForEntity(url, new HttpEntity<String>(outStr, headers), String.class)
                .getBody();
        String json = new String(response.getBytes("ISO-8859-1"), "UTF-8");
        return JSON.parseObject(json);
    }



    public static JSONObject uploadFile(String URL, String filePath, String accessToken, String type) throws Exception {
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            throw new UploadException("文件不存在！");
        }

        String url = URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type);
        TrustManager[] tm = { new MyX509TrustManager() };
        SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
        sslContext.init(null, tm, new java.security.SecureRandom());
        // 从上述SSLContext对象中得到SSLSocketFactory对象
        SSLSocketFactory ssf = sslContext.getSocketFactory();

        URL urlObj = new URL(url);
        // 连接
        HttpsURLConnection conn = (HttpsURLConnection) urlObj.openConnection();
        conn.setSSLSocketFactory(ssf);
        conn.setRequestMethod("POST");
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);   // 使用post提交需要设置忽略缓存

        //消息请求头信息
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");

        //设置边界
        String BOUNDARY = "----------" + System.currentTimeMillis();
        conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);

        StringBuilder sb = new StringBuilder();
        sb.append("--");    // 必须多两道线
        sb.append(BOUNDARY);
        sb.append("\r\n");
        sb.append("Content-Disposition:form-data;name=\"media\";filename=\"" + file.getName() + "\";filelength=\"" + file.length() + "\"\r\n");
        sb.append("Content-Type:application/octet-stream\r\n\r\n");

        byte[] head = sb.toString().getBytes("utf-8");

        // 创建输出流
        OutputStream out = new DataOutputStream(conn.getOutputStream());
        // 获得输出流表头
        out.write(head);

        //文件正文部分
        DataInputStream in = new DataInputStream(new FileInputStream(file));
        int bytes = 0;
        byte[] bufferOut = new byte[1024 * 1024 * 10]; // 10M
        while ((bytes = in.read(bufferOut)) != -1) {
            out.write(bufferOut, 0, bytes);
        }
        in.close();

        //结尾
        byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");
        out.write(foot);
        out.flush();
        out.close();


        // 获取响应
        StringBuffer buffer = new StringBuffer();
        BufferedReader reader = null;
        String result = null;
        try {
            reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            if (result == null) {
                result = buffer.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            reader.close();
        }

        JSONObject json = JSONObject.parseObject(result);
        System.out.println(json);
//        String mediaId = "";
//        if (type.equals("thumb")) {
//            mediaId = json.getString("media_id");
////            System.err.println("a:" + mediaId);
//        }
//        } else {
//            mediaId = json.getString("media_id");
//            System.err.println("b:"+mediaId);
//        }
//        System.err.println(mediaId);
        return json;
    }

    /**
     * POST请求 - Form格式数据
     * @param url 请求地址
     * @param filePath 文件本地路径
     * @return
     */
    public JSONObject doPostForm(String url, String filePath) {
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            throw new UploadException("文件不存在");
        }
        System.err.println(url);
        // 创建SSLContext对象，并使用我们指定的信任管理器初始化
        TrustManager[] tm = { new MyX509TrustManager() };
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL urlObj = new URL(url);
            // 连接
            HttpsURLConnection con = (HttpsURLConnection) urlObj.openConnection();
            con.setSSLSocketFactory(ssf);

            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setUseCaches(false);

            // 设置请求头信息
            con.setRequestProperty("Connection", "Keep-Alive");
            con.setRequestProperty("Charset", "UTF-8");

            // 设置边界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

            String sb = "--" +
                    BOUNDARY +
                    "\r\n" +
                    "Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n" +
                    "Content-Type:application/octet-stream\r\n\r\n";

            byte[] head = sb.getBytes("utf-8");

            // 获得输出流
            OutputStream out = new DataOutputStream(con.getOutputStream());
            // 输出表头
            out.write(head);

            // 文件正文部分
            // 把文件已流文件的方式 推入到url中
            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();

            // 结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线

            out.write(foot);

            out.flush();
            out.close();

            StringBuilder buffer = new StringBuilder();
            BufferedReader reader = null;
            String result = null;
            try {
                // 定义BufferedReader输入流来读取URL的响应
                reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
                result = buffer.toString();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }

            return JSONObject.parseObject(result);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
return null;
    }

    //保存文件
    private String saveFile(MultipartFile file,String account){

        String fileName = file.getOriginalFilename(); //文件名
        System.err.println(fileName);
        String suffixName = fileName.substring(fileName.lastIndexOf("."));// 后缀名
        //http://lfwd.cloudsmicro.com/img/mgg-shop/2.png
        String filePath = "//root//code//img//" + account + "//wxUploadImg//"; // 上传后的路径
        fileName =fileName.substring(0,fileName.lastIndexOf("."))+suffixName; // 新文件名
        File dest = new File(filePath + fileName);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            throw new com.burgeon.backend.service.ex.UploadException("系统错误");
        } catch (Exception e) {
            System.err.println(e.getMessage());
            throw new com.burgeon.backend.service.ex.UploadException("系统错误");
        }

        return filePath + fileName;
    }






}
